import { isAllEmpty, isUrl, openLink, storageLocal } from '@pureadmin/utils'
import Cookies from 'js-cookie'
import { createRouter, type RouteComponent, type Router, type RouteRecordRaw } from 'vue-router'

import { getConfig } from '@/config'
import { useMultiTagsStore } from '@/store/modules/multiTags'

import { usePermissionStore } from '@/store/modules/permission'
import { type DataInfo, multipleTabsKey, userKey } from '@/utils/auth'
import { removeToken } from '@/utils/auth'
import NProgress from '@/utils/progress'
import { buildHierarchyTree } from '@/utils/tree'
import remainingRouter from './modules/remaining'
import {
  ascending,
  findRouteByPath,
  formatFlatteningRoutes,
  formatTwoStageRoutes,
  getHistoryMode,
  getTopMenu,
  handleAliveRoute,
  initRouter,
  isOneOfArray,
} from './utils'

/** 自动导入全部静态路由，无需再手动引入！匹配 src/router/modules 目录（任何嵌套级别）中具有 .ts 扩展名的所有文件，除了 remaining.ts 文件
 * 如何匹配所有文件请看：https://github.com/mrmlnc/fast-glob#basic-syntax
 * 如何排除文件请看：https://cn.vitejs.dev/guide/features.html#negative-patterns
 */
const modules: Record<string, any> = import.meta.glob(
  ['./modules/**/*.ts', '!./modules/**/remaining.ts'],
  { eager: true },
)

/** 原始静态路由（未做任何处理） */
const routes: Array<RouteRecordRaw> = []

Object.keys(modules).forEach(key => {
  routes.push(modules[key].default)
})

/** 导出处理后的静态路由（三级及以上的路由全部拍成二级） */
export const constantRoutes: Array<RouteRecordRaw> = formatTwoStageRoutes(
  formatFlatteningRoutes(buildHierarchyTree(ascending(routes.flat(Infinity)))),
)

/** 用于渲染菜单，保持原始层级 */
export const constantMenus: Array<RouteComponent> = ascending(routes.flat(Infinity)).concat(
  ...remainingRouter,
)

/** 不参与菜单的路由 */
export const remainingPaths = Object.keys(remainingRouter).map(v => {
  return remainingRouter[v].path
})

/** 创建路由实例 */
// history: getHistoryMode(import.meta.env.VITE_ROUTER_HISTORY),
export const router: Router = createRouter({
  history: getHistoryMode('manage'),
  routes: constantRoutes.concat(...(remainingRouter as any)),
  strict: true,
  scrollBehavior(_to, from, savedPosition) {
    return new Promise(resolve => {
      if (savedPosition) {
        return savedPosition
      } else {
        if (from.meta.saveSrollTop) {
          const top: number = document.documentElement.scrollTop || document.body.scrollTop
          resolve({ left: 0, top })
        }
      }
    })
  },
})

/** 重置路由 */
export function resetRouter() {
  router.getRoutes().forEach(route => {
    const { name, meta } = route
    if (name && router.hasRoute(name) && meta?.backstage) {
      router.removeRoute(name)
      router.options.routes = formatTwoStageRoutes(
        formatFlatteningRoutes(buildHierarchyTree(ascending(routes.flat(Infinity)))),
      )
    }
  })
  usePermissionStore().clearAllCachePage()
}

/** 路由白名单 */
const whiteList = ['/login']

const { VITE_HIDE_HOME } = import.meta.env

router.beforeEach((to: ToRouteType, _from, next) => {
  if (to.meta?.keepAlive !== false) {
    handleAliveRoute(to, 'add')
    // 页面整体刷新和点击标签页刷新
    if (_from.name === undefined || _from.name === 'Redirect') {
      handleAliveRoute(to)
    }
  }
  const userInfo = storageLocal().getItem<DataInfo<number>>(userKey)

  NProgress.start()
  const externalLink = isUrl(to?.name as string)
  if (!externalLink) {
    to.matched.some(item => {
      if (!item.meta.title) return ''
      const Title = getConfig().Title
      if (Title) {
        document.title = `${item.meta.title} | ${Title}`
      } else {
        document.title = item.meta.title as string
      }
      return true
    })
  }

  /** 如果已经登录并存在登录信息后不能跳转到路由白名单，而是继续保持在当前页面 */
  function toCorrectRoute() {
    whiteList.includes(to.fullPath) ? next(_from.fullPath) : next()
  }

  if (Cookies.get(multipleTabsKey)) {
    // 无权限跳转403页面
    if (to.meta?.roles && !isOneOfArray(to.meta?.roles as string[], userInfo?.roles || [])) {
      next({ path: '/error/403' })
    }

    // 开启隐藏首页后在浏览器地址栏手动输入首页welcome路由则跳转到404页面
    if (VITE_HIDE_HOME === 'true' && to.fullPath === '/welcome') {
      next({ path: '/error/404' })
    }

    if (_from?.name) {
      // name为超链接
      if (externalLink) {
        openLink(to?.name as string)
        NProgress.done()
      } else {
        toCorrectRoute()
      }
    } else {
      // 刷新
      if (usePermissionStore().wholeMenus.length === 0 && to.path !== '/login') {
        initRouter().then((r: unknown) => {
          const router = r as Router
          const multiTagsStore = useMultiTagsStore()
          if (!multiTagsStore.getMultiTagsCache) {
            const { path } = to
            const route = findRouteByPath(path, router?.options?.routes?.[0]?.children || [])
            getTopMenu(true)
            // query、params模式路由传参数的标签页不在此处处理
            if (route && route.meta?.title) {
              if (isAllEmpty(route.parentId) && route.meta?.backstage) {
                // 此处为动态顶级路由（目录）
                const { path, name, meta } = route.children[0]
                multiTagsStore.handleTags('push', { path, name, meta })
              } else {
                const { path, name, meta } = route
                multiTagsStore.handleTags('push', { path, name, meta })
              }
            }
          }
          // 确保动态路由完全加入路由列表并且不影响静态路由（注意：动态路由刷新时router.beforeEach可能会触发两次，第一次触发动态路由还未完全添加，第二次动态路由才完全添加到路由列表，如果需要在router.beforeEach做一些判断可以在to.name存在的条件下去判断，这样就只会触发一次）
          if (isAllEmpty(to.name)) router.push(to.fullPath)
        })
      }
      toCorrectRoute()
    }
  } else {
    if (to.path !== '/login') {
      if (whiteList.includes(to.path)) {
        next()
      } else {
        removeToken()
        next({ path: '/login' })
      }
    } else {
      next()
    }
  }
})

router.afterEach(() => {
  NProgress.done()
})

export default router
